<template>
  <el-select :id="name"  v-model="valueModel" :placeholder="placeholder"
             :value="valueModel" @change="onChange" clearable multiple>
    <el-option v-if="selectAll" label="- 查询全部 -" value=""></el-option>
    <el-option v-for="item in opts" :key="item.value"
               :label="item.label" :value="item.value"></el-option>
  </el-select>
</template>

<script setup>
import {ref, watch, inject} from 'vue';
import Layers from "@/lang/layers/index";

import Asserts from "@/lang/core/asserts";
import setting from "@/widget/provider/setting";

/**
 * 复选框
 */
const props = defineProps({
    // 字段名
    name: {type: String}
    // 默认值，注意 value 是单向输入，需要通过 change 事件侦听变化
    , value: {type: [String, Array], default: undefined}
    // 数据字典
    , options: {type: [Array, String], default: undefined}
    // 文字提示
    , placeholder: {type: String, default: ''}
    // 选中全部
    , selectAll: {type: Boolean, default: false}

    // 可清除
    , clearable: {type: Boolean, default: true}
    // 请求参数，变更会触发查询函数
    , where: {type: Object, default: undefined}
    // 异步获取函数
    , provider: {type: Function, default: setting.queryDictionary}
});

// Emits
const emit = defineEmits(['change']);

/**
 * 组件使用的对象模型
 *
 * @type {FastForm}
 */
const fast_form = inject('fast_form');

/**
 * 组件使用的对象模型
 *
 * @type {FormInput}
 */
const input = fast_form.getFormInput(props.name);
Asserts.notBlank(input, 'form input is undefined:' + props.name);

// 组件 ID
const id = ref(input.id);

// 定义要触发的事件，用于更新 v-model 的值
const valueModel = ref([]);

// 数据加载状态
const loading = ref(false);

// 数据字典
const opts = ref([]);

/**
 * 监听父组件传递的 value 变化
 *
 * 如果发生变化，通知到 FormInput，由 FormInput 进行业务流转
 */
watch(() => props.value, (val) => {
    input.setValue(val);
});

/**
 * 监听父组件传递的 options 变化
 *
 * 如果发生变化，更新下拉框的选项
 */
watch(() => props.options, (val) => {
    setOptions(val)
});

/**
 * 监听父组件传递的 where 变化
 *
 * 如果发生变化，将 where 作为参数，触发刷新函数
 */
watch(() => props.where, (val) => {
    reload(val);
});

/**
 * 用户输入变换事件
 *
 * 通知到 FormInput，由 FormInput 进行业务流转
 *
 * @param val
 */
const onChange = (val) => {
    emit('change', val);
    input.changeValue(val);
}

/**
 * 数据受控函数
 *
 * 数据发生变化的时候，会通知到当前组件
 *
 * @see FormInput
 * @param val
 */
const onChangeValue = (val) => {
    valueModel.value = val;
}

/**
 * 设值数据字典
 *
 * @param val 字典
 */
const setOptions = (val) => {
    if (Layers.isEmpty(val)) {
        opts.value = [];
    } else if (Array.isArray(val)) {
        opts.value = val;
    } else if (typeof val === 'string') {
        this.reload(val);
    }
}

/**
 * 查询远程数据字典
 */
const reload = (params) => {
    loading.value = true;
    props.provider(params).then(ret => {
        opts.value = ret.list;
    }).finally(() => {
        loading.value = false;
    });
}

// 初始化：设置下拉选项
{
    if (Layers.isNotBlank(props.options)) {
        // 下拉数据选项
        setOptions(props.options);
    } else if (Layers.isNotBlank(props.where)) {
        // 查询远程数据字典
        reload(props.where);
    }

    // 通知到 FormInput，由 FormInput 进行业务流转
    input.setValue(props.value);
}

// 注册输入组件侦听
input.setDom({onChangeValue})
</script>